﻿using System;
using System.Collections.Generic;
using MyLibrary.API.Core;
using System.Linq;
using System.Text;
using System.Xml;
using Newtonsoft.Json;

namespace MyLibrary.API.Json
{
    public class JsonParser
    {
        public static string Success(string message)
        {
            return General(true, message);
        }

        public static string Success<T>(string message, List<T> data) where T: class
        {
            return General<T>(true, message, data);
        }

        public static string Success<T>(string message, List<T> data, int start, int limit) where T : class
        {
            return General(true, message, data, start, limit);
        }

        public static string Failure(string message)
        {
            return General(false, message);
        }

        public static string Failure<T>(string message, List<T> data) where T : class
        {
            return General<T>(false, message, data);
        }

        private static string General(bool success, string message)
        {
            return JsonConvert.SerializeObject(Response.Create(success, message), Newtonsoft.Json.Formatting.Indented);
        }

        private static string General<type>(bool success, string message, List<type> data) where type : class
        {
            return General(success, message, data, default(int?), default(int?));
        }

        private static string General<type>(bool success, string message, List<type> data, int? start, int? limit) where type : class
        {
            int count = data.Count;
            if (start.HasValue && limit.HasValue)
            {
                data = data.Skip(start.Value).Take(limit.Value).ToList();
            }
            return JsonConvert.SerializeObject(ResponseObject<type>.Create(success, message, data, count), Newtonsoft.Json.Formatting.Indented);
        }

        public static string Success(string path, string message, string children)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(path);

            return Success(doc, message, children);
        }

        public static string Success(XmlDocument doc, string message, string children)
        {
            return GeneralXML(true, message, doc, children);
        }

        private static string GeneralXML(bool success, string message, XmlDocument doc, string children)
        {                                
            XmlNodeList list = doc.GetElementsByTagName(children);

            StringBuilder json = new StringBuilder();
            json.AppendLine("{");
            json.Append("\"success\":");
            json.Append(success ? "true": "false");
            json.AppendLine(",");
            json.Append("\"message\":");
            json.Append("\"" + FormatMessage(message) + "\"");
            json.AppendLine(",");

            bool first = true;
            json.Append("\"data\": [");
            foreach (XmlNode node in list)
            {
                if (!first)
                    json.Append(",");

                json.Append(FormatAttribute(JsonConvert.SerializeXmlNode(node, Newtonsoft.Json.Formatting.Indented)));
                first = false;
            }
            json.AppendLine("]}");

            return json.ToString();
        }

        private static string FormatMessage(string message)
        {
            return message = message.Replace('\"', '\'');
        }

        private static string FormatAttribute(string item)
        {
            return item.Replace("@", "_");
        }

        #region Response
        internal struct Response
        {
            public bool success;
            public string message;

            private Response(bool success, string message)
            {
                this.success = success;
                this.message = message;
            }

            public static Response Create(bool success, string message)
            {
                return new Response(success, message);
            }
        }

        internal struct ResponseObject<T> where T: class
        {
            public bool success;
            public string message;
            public int total;
            public List<T> data;

            private ResponseObject(bool success, string message, List<T> objects, int total)
            {
                this.success = success;
                this.message = message;
                data = objects;
                this.total = total;
            }      

            public static ResponseObject<T> Create(bool success, string message, List<T> objects)
            {
                return Create(success, message, objects, objects.Count);
            }

            public static ResponseObject<T> Create(bool success, string message, List<T> objects, int total)
            {
                return new ResponseObject<T>(success, message, objects, total);
            }
        }
        #endregion
    }
}
